package com.feng.fengDUtil.dao;

import com.feng.fengDUtil.dao.exception.IdPkConflictOrBothNullException;
import com.feng.fengDUtil.dao.pojo.InsertTypeEnum;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class TableInfo {

  private String tableName;
  private FieldInfo idFieldInfo;
  private List<FieldInfo> pkFieldList;
  private List<FieldInfo> fieldList;
  private List<FieldInfo> fieldWithoutIdPkList = new ArrayList();

  private List<PopulateInfo> populateList;

  private String baseSelectSql;
  private String insertSql;
  private String updateSql;
  private String selectByIdSql;
  private String selectByPkSql;
  private String batchUpdateSqlInner;
  private String batchUpdateSqlOuter;

  public TableInfo() {
  }

  public void generateSql() {
    generateBaseSelectSql();
    generateSelectByIdSql();
    generateSelectByPkSql();
    generateInsertSql();
    generateUpdateSql();
    generateBatchUpdateSql();
  }

  private void generateBaseSelectSql() {
    List allField;
    if (idFieldInfo != null) {
      allField = new ArrayList();
      allField.add(idFieldInfo);
      allField.addAll(fieldList);
    } else {
      allField = fieldList;
    }
    StringBuilder sb = new StringBuilder("select ");
    sb.append(SqlUtil.geneSelectPart(allField)).append(" from ").append(tableName);
    baseSelectSql = sb.toString();
  }

  private void generateSelectByIdSql() {
    if (idFieldInfo != null) {
      StringBuilder sb = new StringBuilder(baseSelectSql);
      sb.append(" where ").append(idFieldInfo.getColumnName()).append(" = ? ");
      selectByIdSql = sb.toString();
    }
  }

  private void generateSelectByPkSql() {
    if (pkFieldList != null) {
      selectByPkSql = SqlUtil.geneSelectByPkSql(baseSelectSql, pkFieldList);
    }
  }

  private void generateInsertSql() {
    List<FieldInfo> fieldList = new ArrayList();
    if (idFieldInfo != null) {
      fieldList.add(idFieldInfo);
    }
    fieldList.addAll(this.fieldList);

    insertSql = SqlUtil.geneInsertSql(tableName, fieldList);
  }


  private void generateUpdateSql() {
    if (idFieldInfo != null) {
      updateSql = SqlUtil.geneUpdateSql(tableName, idFieldInfo.getColumnName(), fieldList);
    } else if (pkFieldList != null) {
      updateSql = SqlUtil.geneUpdateSqlPk(tableName, pkFieldList, fieldWithoutIdPkList);
    } else {
      throw new IdPkConflictOrBothNullException();
    }
  }

  public List<FieldInfo> getAllFields() {
    List<FieldInfo> allFields = new ArrayList<>();
    if (idFieldInfo != null) {
      allFields.add(idFieldInfo);
    }
    allFields.addAll(fieldList);
    return allFields;
  }

  private void generateBatchUpdateSql() {
    if (idFieldInfo != null) {
      List<FieldInfo> allFields = new ArrayList<>();
      allFields.add(idFieldInfo);
      allFields.addAll(fieldList);
      batchUpdateSqlInner = SqlUtil.geneBatchUpdateSqlInner(tableName, allFields);
      batchUpdateSqlOuter = SqlUtil.geneBatchUpdateSqlOuter(tableName, Arrays.asList(idFieldInfo), fieldList);
    } else if (pkFieldList != null) {
      batchUpdateSqlInner = SqlUtil.geneBatchUpdateSqlInner(tableName, fieldList);
      batchUpdateSqlOuter = SqlUtil.geneBatchUpdateSqlOuter(tableName, pkFieldList, fieldWithoutIdPkList);
    } else {
      throw new IdPkConflictOrBothNullException();
    }
  }

  public String getInsertSql(InsertTypeEnum insertType) {
    return new StringBuilder(insertType.getSqlPart()).append(insertSql).toString();
  }

  public void addPopulate(PopulateInfo populateInfo) {
    if (populateList == null) {
      populateList = new ArrayList<>();
    }
    populateList.add(populateInfo);
  }

  public List<PopulateInfo> getPopulateList() {
    return populateList;
  }

  @Override
  public String toString() {
    return "tableName = " + tableName + " ,fieldList.size=" + fieldList
        .size() + ",\nidFieldInfo = " + idFieldInfo + "\nfieldList = \n" + fieldList;
  }
}
